package com.wzcl.app.service.impl;

import com.wzcl.app.dao.model.*;
import com.wzcl.app.dao.repository.*;
import com.wzcl.app.model.common.MyPage;
import com.wzcl.app.model.common.RVO;
import com.wzcl.app.model.dto.WorkShowDto;
import com.wzcl.app.model.vo.WorkShowDataCountVo;
import com.wzcl.app.service.CourseService;
import com.wzcl.app.service.WorkShowService;
import com.wzcl.app.utils.DateUtil;
import com.wzcl.app.utils.CollectionUtil;
import com.wzcl.app.utils.StringUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.persistence.Transient;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author beingven
 * @Description 作品秀
 * @createTime 2020年12月11日 14:57:00
 */
@Service
public class WorkShowServiceImpl implements WorkShowService {
    @Resource
    private WorkShowRepository workShowRepository;
    @Resource
    private CourseRepository courseRepository;
    @Resource
    private UserCourseRepository userCourseRepository;
    @Resource
    private EssayCourseCatalogRepository catalogRepository;
    @Resource
    private TaskEvaluateScoreRepository taskEvaluateScoreRepository;
    @Resource
    private AppUserRepository appUserRepository;
    @Resource
    private CourseTeacherRepository courseTeacherRepository;
    @Resource
    private CourseService courseService;

    /**
     * 添加作品秀
     * @param workShowDto 作品秀对象
     * @return 返回已添加的作品秀
     */
    @Override
    public WorkShow createWorkShow(WorkShowDto workShowDto) {
        String phone = SecurityContextHolder.getContext().getAuthentication().getName();
        WorkShow workShow = new WorkShow();
        //获取时间系统当前
        long time = System.currentTimeMillis();
        workShow.setCreateTime(DateUtil.getDateBySystemTime(time));
        workShow.setUpdateTime(DateUtil.getDateBySystemTime(time));
        //创建作品秀初始获赞0
        workShow.setLikeNumber(0);
        //初始为未点评
        workShow.setIsComment(0);
        //初始为未推送
        workShow.setPushStatus(0);
        //初始为未审核
        workShow.setCheckStatus(0);
        //拼接图片
        workShow.setImage(CollectionUtil.getStringFromList(workShowDto.getImageList(), ";"));
        workShow.setCourse(courseRepository.findAllByCourseId(workShowDto.getCourseId()));
        workShow.setCatalog(catalogRepository.findCatalogById(workShowDto.getCatalogId()));
        workShow.setAppUser(appUserRepository.findByPhone(phone));
        // 保存作品秀到数据库
        return  workShowRepository.save(workShow);
    }

    @Override
    public WorkShow retrieveWorkShowById(Integer id) {
        return workShowRepository.findWorkShowById(id);
    }

    /**
     * 根据作品秀id删除作品秀
     * @param id 作品秀id
     */
    @Override
    public void deleteWorkShowById(Integer id) {
        workShowRepository.deleteById(id);
    }

    /**
     * 根据id更新作品秀
     * @param workShowDto 作品秀对象
     */
    @Override
    public void updateWorkShowById(WorkShowDto workShowDto) {
        String list = CollectionUtil.getStringFromList(workShowDto.getImageList(), ";");
        workShowRepository.updateImageById(workShowDto.getId(), list, DateUtil.getDateBySystemTime(System.currentTimeMillis()));
    }

    /**
     * 根据条件分页查询当前用户作品秀
     * @param workShowDto 作品秀对象
     * @return 返回用户作品秀分页数据
     */
    @Override
    public MyPage<WorkShow> retrieveAllByUserIdByPage(WorkShowDto workShowDto) {
        System.out.println(workShowDto);
        Page all = workShowRepository.findAll(getAllSpecification(workShowDto), workShowDto.getPageable());
        return new MyPage<>(all);
    }

    /**
     * 根据年级分页查询作品秀
     * @param workShowDto 作品秀对象
     * @return 返回分页后的作品秀
     */
    @Override
    public MyPage<WorkShow> retrieveAllByUserIdAndGradeByPage(WorkShowDto workShowDto) {
        ArrayList<WorkShow> allByGrandName = null;
        if (workShowDto.getGrade() == null){
            allByGrandName = workShowRepository.findAllWorkShow();
        }else {
            allByGrandName = workShowRepository.findAllByGrandName(workShowDto.getGrade());
        }
        List<WorkShow> listBySort = CollectionUtil.getListBySort(allByGrandName, "getUpdateTime", "desc");
        List<WorkShow> listByPage = CollectionUtil.getListByPage(listBySort, workShowDto.getPageNumber()+1, workShowDto.getPageSize());
        MyPage<WorkShow> myPage = new MyPage<>();
        myPage.setContent(listByPage);
        myPage.setTotalElements(allByGrandName.size());
        return myPage;
    }

    /**
     * 作品秀点赞，取消
     * @param id 作品秀id
     * @return 返回点赞状态
     */
    @Override
    @Transactional
    public RVO giveLike(Integer id){
        String phone = SecurityContextHolder.getContext().getAuthentication().getName();
        AppUser appUser = appUserRepository.findByPhone(phone);
        //判断用户是否为游客
        if (phone == null || phone == ""){
            return RVO.error("用户未注册");
        }
        //获取用户id
        Integer userId = appUser.getId();
        //获取用户头像
        String headIcon = appUser.getHeadIcon();
        //获取当前作品秀点赞的用户集合
        WorkShow workShow = workShowRepository.findLikeById(id);
        //String转为List
        List<String> list = CollectionUtil.getListFromString(workShow.getLikeOfPerson(), ",");
        //获取当前用户点赞的头像
        List<String> iconList = CollectionUtil.getListFromString(workShow.getLikeIconList(), ",");
        //判断用户是否已经点赞
        if (list.contains(userId.toString())){
            //取消点赞
            if (list.size() == 1){
                list.clear();
                iconList.clear();
                workShowRepository.updateLikeDataById(workShow.getLikeNumber()-1, null, null, DateUtil.getDateBySystemTime(System.currentTimeMillis()), id);
            }else {
                //取消点赞需要删除userId对应的头像（为了避免删除一样的头像）
                int index = list.indexOf(userId.toString());
                list.remove(index);
                iconList.remove(index);
                String newList = CollectionUtil.getStringFromList(list, ",");
                String newIconList = CollectionUtil.getStringFromList(iconList, ",");
                workShowRepository.updateLikeDataById(workShow.getLikeNumber()-1, newList, newIconList, DateUtil.getDateBySystemTime(System.currentTimeMillis()), id);
            }
            return RVO.success("取消点赞");
        }else {
            //点赞
            list.add(userId.toString());
            iconList.add(headIcon);
            String newList = CollectionUtil.getStringFromList(list, ",");
            String newIconList = CollectionUtil.getStringFromList(iconList, ",");
            workShowRepository.updateLikeDataById(workShow.getLikeNumber()+1, newList, newIconList, DateUtil.getDateBySystemTime(System.currentTimeMillis()), id);
            return RVO.success("点赞成功");
        }
    }

    /**
     * 推送/取消优秀作品
     * @param id 作品秀id
     * @return 返回推送状态
     */
    @Override
    public RVO isPush(Integer id) {
        //获取作品秀推送状态
        WorkShow workShow = workShowRepository.findWorkShowById(id);
        if (workShow.getPushStatus() == 0) {
            //更新为已推送
            workShowRepository.updatePushStatusById(1, id);
            return RVO.success("已推送");
        }
        workShowRepository.updatePushStatusById(0, id);
        return RVO.success("已取消推送");
    }

    /**
     * 自定义指定作品秀的虚拟点赞数
     * @param id 作品秀id
     * @param virtualLikeNumber 自定义点赞数
     * @return 返回修改状态
     */
    @Override
    @Transactional
    public RVO updateLikeNumber(Integer id, Integer virtualLikeNumber) {
        //点赞数不能超过30
        //获取所有用户id的list
        List<String> allId = appUserRepository.findAllId();
        //随机取出一些用户用于制造点赞的假数据
        Set<String> set = CollectionUtil.getUniqueListFromList(allId, 3);
        String stringFromSet = CollectionUtil.getStringFromSet(set, ",");
        //更新点赞数据
        workShowRepository.updateVirtualLikeDataById(virtualLikeNumber, stringFromSet, DateUtil.getDateBySystemTime(System.currentTimeMillis()), id);
        return RVO.success("点赞数据更新成功");
    }

    /**
     * 优秀作品/当前课程下优秀作品列表展示
     * @param workShowDto 作品秀对象
     * @return 返回优秀作品分页数据
     */
    @Override
    public MyPage<WorkShow> getPageByExcellent(WorkShowDto workShowDto) {
        //查询已推送作品
        return new MyPage<>(workShowRepository.findAll(getSpecification(workShowDto), workShowDto.getPageable()));
    }

    @Override
    public List<WorkShow> getPageByNotComment(WorkShowDto workShowDto) {
        String phone = SecurityContextHolder.getContext().getAuthentication().getName();
        //截取userId的值
        AppUser appUser = appUserRepository.findByPhone(phone);
        List<Integer> courseIdList = courseTeacherRepository.findAllByUserId(Integer.valueOf(appUser.getId()));
        //查询当前教师的所有课程
        List<WorkShow> workShowList = workShowRepository.findAll(getAllSpecification(workShowDto));
        //排除当前教师课程以外其他教师课程下的作品秀
        for (int index = 0; index < workShowList.size(); index++) {
            //如果作品秀的关联课程id不在courseIdList中则不是当前教师的课程下的作品秀
            if (!courseIdList.contains(workShowList.get(index).getCourse().getId())) {
                workShowList.remove(index);
                index --;
            }
        }
        //排序
        List<WorkShow> listByPage = CollectionUtil.getListByPage(workShowList, workShowDto.getPageNumber() + 1, workShowDto.getPageSize());
        return listByPage;
    }

    @Override
    public WorkShowDataCountVo getWorkShowDataByUserId(Integer userId) {
        AppUser appUser = appUserRepository.findAllById(userId);
        Long likeNumber = 0l;
        //查询用户所有作品秀
        List<WorkShow> workShowList = workShowRepository.findAllByUserId(userId);
        //统计所有点赞
        for (int index = 0; index < workShowList.size(); index++) {
            likeNumber += (workShowList.get(index).getLikeNumber()+workShowList.get(index).getVirtualLikeNumber());
        }

        //阅读能量(规则：用户完成一个任务获得100阅读能量，完成整个章节额外获得20阅读能量，完成整个作文课额外获得50阅读能量)
        //查询当前用户购买的作文课
        //
        Long catalogPower = 0l;
        Long coursePower = 0l;
        List<UserCourse> userCourseList = userCourseRepository.findAllByCourseType(appUser.getPhone(), 10);
        List<CatalogTask> catalogTaskList = new ArrayList<>();
        for (int index = 0; index < userCourseList.size(); index++) {
            //获取课程下的所有任务
            List<CatalogTask> taskList = courseService.getAllTaskByCourse(userCourseList.get(index).getCourse().getId());
            catalogTaskList.addAll(taskList);
            //获取课程下的已完成章节
            List<EssayCourseCatalog> catalogList = courseService.getAllCatalogByCourse(userCourseList.get(index).getCourse().getId());
            catalogPower += catalogList.size() * 20l;
            if (catalogList.size() == catalogRepository.findAllByCourseId(userCourseList.get(index).getCourse().getId()).size()){
                //整个课程已完成，添加额外阅读能量
                coursePower += 50;
            }
        }
        //筛选已完成的任务
        Long taskPower = 0l;
        for (int index = 0; index < catalogTaskList.size(); index++) {
            TaskEvaluateScore taskEvaluateScore = taskEvaluateScoreRepository.findByTaskId(catalogTaskList.get(index).getId(), appUser.getPhone());
            if (taskEvaluateScore == null){
                catalogTaskList.remove(index);
                index --;
                break;
            }
            taskPower += 100;
        }

        WorkShowDataCountVo workShowDataCountVo = new WorkShowDataCountVo();
        workShowDataCountVo.setAppUser(appUser);
        workShowDataCountVo.setLikeNumberCount(likeNumber);
        workShowDataCountVo.setReadEnergy(taskPower + catalogPower + coursePower);
        workShowDataCountVo.setWorksNumber(workShowList.size());
        return workShowDataCountVo;
    }

    @Override
    public RVO updateWorkShowByCheckStatus(Integer id, Integer checkStatus) {
        workShowRepository.updateWorkShowCheckStatus(id, checkStatus);
        return RVO.success("审核状态更新");
    }

    //条件筛选
    public Specification<WorkShow> getSpecification(WorkShowDto workShowDto){
        return (Specification<WorkShow>) (root, criteriaQuery, criteriaBuilder) -> {
            ArrayList<Predicate> list = new ArrayList<>();
            //条件过滤
            if (workShowDto.getCourseId() != null){
                //创建到指定属性的内部连接
                Join<WorkShow, Course> course = root.join("course");
                list.add(criteriaBuilder.equal(course.get("id"), workShowDto.getCourseId()));
            }
            list.add(criteriaBuilder.equal(root.get("checkStatus"),1));
            // 排序
            criteriaQuery.orderBy(criteriaBuilder.desc(root.get("updateTime")));
            //将两个查询条件联合起来之后返回Predicate对象
            return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
        };
    }

    /**
     * 根据作品秀id获取作品秀详情
     * @param id
     * @return
     */
    public WorkShowDto getWorkShowDetails(Integer id){
        return new WorkShowDto();
    }

    /**
     * 分页查询条件拼接(按用户id过滤，按更新时间排序并分页)
     * @param workShowDto 作品秀对象
     * @return 过滤后的数据
     */
    public Specification<WorkShow> getAllSpecification(WorkShowDto workShowDto){
        return (Specification<WorkShow>) (root, criteriaQuery, criteriaBuilder) -> {
            ArrayList<Predicate> list = new ArrayList<>();
            //root.get("address")表示获取address这个字段名称,like表示执行like查询,%zt%表示值
            //Predicate p1 = criteriaBuilder.like(root.get("address"), "%zt%");
            //Predicate p2 = criteriaBuilder.greaterThan(root.get("id"),3);
            //条件过滤
            if (workShowDto.getUserId() != null){
                //创建到指定属性的内部连接
                Join<WorkShow, AppUser> appUser = root.join("appUser");
                list.add(criteriaBuilder.equal(appUser.get("id"), workShowDto.getUserId()));
            }
            if (workShowDto.getPushStatus() != null){
                //创建到指定属性的内部连接
                list.add(criteriaBuilder.equal(root.get("pushStatus"), workShowDto.getPushStatus()));
            }
            if (workShowDto.getIsComment() != null){
                //筛选条件是否点评
                list.add(criteriaBuilder.equal(root.get("isComment"), workShowDto.getIsComment()));
            }
            if (workShowDto.getCourseId() != null){
                //课程id
                Join<WorkShow, Course> course = root.join("course");
                list.add(criteriaBuilder.equal(course.get("id"), workShowDto.getCourseId()));
            }
            if (workShowDto.getCatalogId() != null){
                //章节下的作品秀
                Join<WorkShow, Course> catalog = root.join("catalog");
                list.add(criteriaBuilder.equal(catalog.get("id"), workShowDto.getCatalogId()));
            }
            if (workShowDto.getCheckStatus() != null){
                //是否审核
                list.add(criteriaBuilder.equal(root.get("checkStatus"), workShowDto.getCheckStatus()));
            }
            if (workShowDto.getCheckStatus() == null){
                //是否审核
                list.add(criteriaBuilder.equal(root.get("checkStatus"), 1));
            }
            // 排序
            criteriaQuery.orderBy(criteriaBuilder.desc(root.get("updateTime")));
            //将两个查询条件联合起来之后返回Predicate对象
            return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
        };
    }
}